// Google test includes
#include <gtest/gtest.h>
#include <gmock/gmock.h>

// Tested file
#include "Utils/Compare.h"

// Mocks and fakes
#include "MockNode.h"

using namespace testing;

TEST(CompareNodesTest, DifferentNumberOfChildren)
{
	// Prepare arguments
	StrictMock<TestNode> left(NT_ATOM);
	EXPECT_CALL(left, getChildrenCount()).WillOnce(Return(1));
	StrictMock<TestNode> right(NT_ATOM);
	EXPECT_CALL(right, getChildrenCount()).WillOnce(Return(2));

	// Check that nodes with different number of children are different
	EXPECT_FALSE(compareNodes<TestNode>(&left, &right));
}

TEST(CompareNodesTest, DifferentNodeTypes)
{
	// Prepare arguments
	StrictMock<TestNode> left(NT_ATOM);
	EXPECT_CALL(left, getChildrenCount()).WillOnce(Return(1));
	StrictMock<TestNode> right(NT_OR);
	EXPECT_CALL(right, getChildrenCount()).WillOnce(Return(2));

	// Check that nodes with different number of children are different
	EXPECT_FALSE(compareNodes<TestNode>(&left, &right));
}

TEST(CompareNodesTest, DifferentChildren)
{
	// Prepare arguments
	StrictMock<TestNodeAnd> left;
	EXPECT_CALL(left, getChildrenCount()).WillRepeatedly(Return(1));
	StrictMock<TestNodeAnd> right;
	EXPECT_CALL(right, getChildrenCount()).WillRepeatedly(Return(1));

	// Prepare children
	StrictMock<TestNode> leftChild(NT_NOT);
	StrictMock<TestNode> rightChild(NT_NOT);
	EXPECT_CALL(left, getChild(0)).WillOnce(Return(&leftChild));
	EXPECT_CALL(right, getChild(0)).WillOnce(Return(&rightChild));
	EXPECT_CALL(leftChild, compare(&rightChild)).WillOnce(Return(false));

	// Check that nodes with different number of children are different
	EXPECT_FALSE(compareNodes<TestNode>(&left, &right));
}

TEST(CompareNodesTest, NodesEqual)
{
	// Prepare arguments
	StrictMock<TestNodeAnd> left;
	EXPECT_CALL(left, getChildrenCount()).WillRepeatedly(Return(3));
	StrictMock<TestNodeAnd> right;
	EXPECT_CALL(right, getChildrenCount()).WillRepeatedly(Return(3));

	// Prepare children
	StrictMock<TestNode> leftChild(NT_NOT);
	StrictMock<TestNode> rightChild(NT_NOT);

	// Force all children will be represented by leftChild and rightChild
	EXPECT_CALL(left, getChild(0)).WillOnce(Return(&leftChild));
	EXPECT_CALL(right, getChild(0)).WillOnce(Return(&rightChild));
	EXPECT_CALL(left, getChild(1)).WillOnce(Return(&leftChild));
	EXPECT_CALL(right, getChild(1)).WillOnce(Return(&rightChild));
	EXPECT_CALL(left, getChild(2)).WillOnce(Return(&leftChild));
	EXPECT_CALL(right, getChild(2)).WillOnce(Return(&rightChild));

	// Assume that all children are equal
	EXPECT_CALL(leftChild, compare(&rightChild)).WillRepeatedly(Return(true));

	// Check that nodes with different number of children are different
	EXPECT_TRUE(compareNodes<TestNode>(&left, &right));
}

